Pallial transition state cells

Extract apical progenitors

We perform Kmeans clustering on the 4 cell state scores :

  • Sub-pallial neurons SP
  • Pallial neurons Pal
  • Sub-pallial BP SP.BP
  • Pallial BP Pal.BP

We then extract the Pallial cells branche. We also excludes CR cells cluster form the trajectory inference.

#Remove the sub-pallial cells branche
MeanKclust.SPscore <- aggregate(SP_signature1 ~ kmeanClust, Allcells.data@meta.data, mean)
SPclust <- MeanKclust.SPscore %>% filter(SP_signature1 == max(SP_signature1)) %>% pull(kmeanClust)

SP.cells <- Allcells.data@meta.data %>% filter(kmeanClust == SPclust) %>% pull(Barcodes)

# Remove cells not use for trajectory inference (Subpallial cells defined by kmeans, Late GABA neurons and CR cells)
Excluded.clusters <- Allcells.data@meta.data %>%
                  filter(Cluster.ident %in% grep("*Sub|GABA|LN.Glut.13|LN.Glut.14|LN.Glut.1$", unique(as.character(Allcells.data@ident)), value = T)) %>%
                  pull(Barcodes) 

# We further keep only pallial apical progenitor cluster among other AP clusters
MeanKclust.APscore <- aggregate(AP_signature1 ~ kmeanClust, Allcells.data@meta.data, mean)
APclust <- MeanKclust.APscore %>% filter(AP_signature1 == max(AP_signature1)) %>% pull(kmeanClust)

All.AP <- Allcells.data@meta.data %>% filter(kmeanClust == APclust) %>% pull(Barcodes)
Valide.AP <- Allcells.data@meta.data %>% filter(Cluster.ident %in% grep("Dorsal.Pallium|lateral.Pallium.1|lateral.Pallium.2|Ventral.Pallium",
                                                unique(as.character(Allcells.data@ident)), value = T)) %>% pull(Barcodes)

filtered.AP <- All.AP[!All.AP %in% Valide.AP]

#Remove all invalide cells + 3 pallial outlier cells
Cells.to.use <- rownames(Allcells.data@meta.data)[!rownames(Allcells.data@meta.data) %in% unique(c(SP.cells, Excluded.clusters, filtered.AP, c("ATTTCTGCACGGCCAT" , "CAAGTTGCAAGCCTAT", "CTACATTGTAGCTGCC")))]
Allcells.data <- SubsetData(Allcells.data, cells.use = Cells.to.use, subset.raw = T,  do.clean = F)

Compute cells’ fate bias along tpward each mature neuronal types

Prepare FateID input data

We restricted the analysis to the most variable genes as dertermined by the Seurat function “FindVariableGenes” excluding cell cylce phase genes

Compte the cells’ fate bias

## minnr: 10 
## minnrh: 30 
## test set size iteration 1 : 10 10 10 10 10 10 10 
## randomforest iteration 1 of 50 cells
## test set size iteration 2 : 10 10 10 10 10 10 10 
## randomforest iteration 2 of 62 cells
## test set size iteration 3 : 10 10 10 10 10 10 10 
## randomforest iteration 3 of 53 cells
## test set size iteration 4 : 10 10 10 10 10 10 10 
## randomforest iteration 4 of 55 cells
## test set size iteration 5 : 10 10 10 10 10 10 10 
## randomforest iteration 5 of 49 cells
## test set size iteration 6 : 10 10 10 10 10 10 10 
## randomforest iteration 6 of 48 cells
## test set size iteration 7 : 10 10 10 10 10 10 10 
## randomforest iteration 7 of 54 cells
## test set size iteration 8 : 10 10 10 10 10 10 10 
## randomforest iteration 8 of 49 cells
## test set size iteration 9 : 10 10 10 10 10 10 10 
## randomforest iteration 9 of 50 cells
## test set size iteration 10 : 10 10 10 10 10 10 10 
## randomforest iteration 10 of 51 cells
## test set size iteration 11 : 10 10 10 10 10 10 10 
## randomforest iteration 11 of 52 cells
## test set size iteration 12 : 10 10 10 10 10 10 10 
## randomforest iteration 12 of 44 cells
## test set size iteration 13 : 10 10 10 10 10 10 10 
## randomforest iteration 13 of 45 cells
## test set size iteration 14 : 10 10 10 10 10 10 10 
## randomforest iteration 14 of 42 cells
## test set size iteration 15 : 10 10 10 10 10 10 10 
## randomforest iteration 15 of 43 cells
## test set size iteration 16 : 10 10 10 10 10 10 10 
## randomforest iteration 16 of 40 cells
## test set size iteration 17 : 10 10 10 10 10 10 10 
## randomforest iteration 17 of 40 cells
## test set size iteration 18 : 10 10 10 10 10 10 10 
## randomforest iteration 18 of 37 cells
## test set size iteration 19 : 10 10 10 10 10 10 10 
## randomforest iteration 19 of 42 cells
## test set size iteration 20 : 10 10 10 10 10 10 10 
## randomforest iteration 20 of 43 cells
## test set size iteration 21 : 10 10 10 10 10 10 10 
## randomforest iteration 21 of 48 cells
## test set size iteration 22 : 10 10 10 10 10 10 10 
## randomforest iteration 22 of 47 cells
## test set size iteration 23 : 10 10 10 10 10 10 10 
## randomforest iteration 23 of 50 cells
## test set size iteration 24 : 10 10 10 10 10 10 10 
## randomforest iteration 24 of 52 cells
## test set size iteration 25 : 10 10 10 10 10 10 10 
## randomforest iteration 25 of 53 cells
## test set size iteration 26 : 10 10 10 10 10 10 10 
## randomforest iteration 26 of 57 cells
## test set size iteration 27 : 10 10 10 10 10 10 10 
## randomforest iteration 27 of 54 cells
## test set size iteration 28 : 10 10 10 10 10 10 10 
## randomforest iteration 28 of 49 cells
## test set size iteration 29 : 10 10 10 10 10 10 10 
## randomforest iteration 29 of 54 cells
## test set size iteration 30 : 10 10 10 10 10 10 10 
## randomforest iteration 30 of 51 cells
## test set size iteration 31 : 10 10 10 10 10 10 10 
## randomforest iteration 31 of 50 cells
## test set size iteration 32 : 10 10 10 10 10 10 10 
## randomforest iteration 32 of 55 cells
## test set size iteration 33 : 5 5 5 5 5 5 10 
## randomforest iteration 33 of 36 cells
## test set size iteration 34 : 10 10 10 10 10 10 10 
## randomforest iteration 34 of 56 cells
## test set size iteration 35 : 10 10 10 10 10 10 10 
## randomforest iteration 35 of 55 cells
## test set size iteration 36 : 10 10 10 10 10 10 10 
## randomforest iteration 36 of 55 cells
## test set size iteration 37 : 10 10 10 10 10 10 10 
## randomforest iteration 37 of 54 cells
## test set size iteration 38 : 10 10 10 10 10 10 10 
## randomforest iteration 38 of 56 cells
## test set size iteration 39 : 10 10 10 10 10 10 10 
## randomforest iteration 39 of 58 cells
## test set size iteration 40 : 10 10 10 10 10 10 10 
## randomforest iteration 40 of 47 cells
## test set size iteration 41 : 10 10 10 10 10 10 10 
## randomforest iteration 41 of 44 cells
## test set size iteration 42 : 10 10 10 10 10 10 10 
## randomforest iteration 42 of 30 cells
## test set size iteration 43 : 10 10 10 10 10 10 10 
## randomforest iteration 43 of 18 cells
## test set size iteration 44 : 10 10 10 10 10 10 10 
## randomforest iteration 44 of 2 cells

Extract the Nr4a2 and Nfix “lineage” cells

Aligne cells along Pseudotime

We decided to use spring space dimensionality reduction to fit the principale curve because it has been calculated on all cells together. Thus reflecting pan neuronal differentiation axis of varation.

Find DEG between the two trajectories and along the pseudotime

Find direction of the DEG

We find direction of the DEG by calculating the area between curves (ABC) for branch-dependent genes by adapting the monocle package function calABCs. Genes specific ABC is computed on smoothed expression value over 100 points along the pseudotime

Cluster genes by expression profiles along the two trajectories

Nr4a2 neurons specific transcriptional trajectories

Manuscript Fig. 7D

Manuscript Fig. 7D

Nfix neurons specific transcriptional trajectories

Manuscript Fig. 7C

Manuscript Fig. 7C

Session Info

## [1] "05 novembre, 2020, 17,50"
## R version 3.6.3 (2020-02-29)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.5 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/atlas/libblas.so.3.10.3
## LAPACK: /usr/lib/x86_64-linux-gnu/atlas/liblapack.so.3.10.3
## 
## locale:
##  [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
##  [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
##  [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
##  [1] splines   stats4    parallel  stats     graphics  grDevices utils    
##  [8] datasets  methods   base     
## 
## other attached packages:
##  [1] wesanderson_0.3.6   RColorBrewer_1.1-2  patchwork_0.0.1    
##  [4] ggExtra_0.9         reshape2_1.4.3      dplyr_0.8.3        
##  [7] seriation_1.2-9     FateID_0.1.9        monocle_2.14.0     
## [10] DDRTree_0.1.5       irlba_2.3.3         VGAM_1.1-2         
## [13] Biobase_2.46.0      BiocGenerics_0.32.0 princurve_2.1.4    
## [16] Seurat_2.3.4        Matrix_1.2-17       cowplot_1.0.0      
## [19] ggplot2_3.2.1      
## 
## loaded via a namespace (and not attached):
##   [1] snow_0.4-3           backports_1.1.5      Hmisc_4.3-0         
##   [4] plyr_1.8.4           igraph_1.2.5         lazyeval_0.2.2      
##   [7] densityClust_0.3     lle_1.1              fastICA_1.2-2       
##  [10] digest_0.6.25        foreach_1.4.7        htmltools_0.5.0     
##  [13] viridis_0.5.1        lars_1.2             gdata_2.18.0        
##  [16] magrittr_1.5         checkmate_1.9.4      cluster_2.1.0       
##  [19] mixtools_1.1.0       ROCR_1.0-7           limma_3.42.0        
##  [22] matrixStats_0.55.0   R.utils_2.9.0        docopt_0.6.1        
##  [25] askpass_1.1          colorspace_1.4-1     ggrepel_0.8.1       
##  [28] xfun_0.18            sparsesvd_0.2        crayon_1.3.4        
##  [31] jsonlite_1.7.0       zeallot_0.1.0        survival_2.44-1.1   
##  [34] zoo_1.8-6            iterators_1.0.12     ape_5.3             
##  [37] glue_1.4.1           registry_0.5-1       gtable_0.3.0        
##  [40] kernlab_0.9-29       prabclus_2.3-1       DEoptimR_1.0-8      
##  [43] scales_1.1.0         pheatmap_1.0.12      som_0.3-5.1         
##  [46] bibtex_0.4.2         miniUI_0.1.1.1       Rcpp_1.0.5          
##  [49] metap_1.1            dtw_1.21-3           xtable_1.8-4        
##  [52] viridisLite_0.3.0    htmlTable_1.13.2     reticulate_1.13     
##  [55] foreign_0.8-72       bit_4.0.4            proxy_0.4-23        
##  [58] mclust_5.4.5         SDMTools_1.1-221.1   Formula_1.2-3       
##  [61] tsne_0.1-3           umap_0.2.3.1         htmlwidgets_1.5.1   
##  [64] httr_1.4.1           FNN_1.1.3            gplots_3.0.1.1      
##  [67] fpc_2.2-3            acepack_1.4.1        modeltools_0.2-22   
##  [70] ica_1.0-2            farver_2.0.1         pkgconfig_2.0.3     
##  [73] R.methodsS3_1.7.1    flexmix_2.3-15       nnet_7.3-14         
##  [76] locfit_1.5-9.1       labeling_0.3         later_1.0.0         
##  [79] tidyselect_0.2.5     rlang_0.4.7          munsell_0.5.0       
##  [82] tools_3.6.3          ggridges_0.5.1       fastmap_1.0.1       
##  [85] evaluate_0.14        stringr_1.4.0        yaml_2.2.1          
##  [88] npsurv_0.4-0         knitr_1.26           bit64_4.0.2         
##  [91] fitdistrplus_1.0-14  robustbase_0.93-5    caTools_1.17.1.2    
##  [94] randomForest_4.6-14  purrr_0.3.3          RANN_2.6.1          
##  [97] pbapply_1.4-2        nlme_3.1-141         mime_0.7            
## [100] slam_0.1-46          R.oo_1.23.0          hdf5r_1.3.2.9000    
## [103] compiler_3.6.3       rstudioapi_0.11      png_0.1-7           
## [106] lsei_1.2-0           tibble_2.1.3         stringi_1.4.6       
## [109] highr_0.8            lattice_0.20-41      HSMMSingleCell_1.6.0
## [112] vctrs_0.2.0          pillar_1.4.2         lifecycle_0.1.0     
## [115] combinat_0.0-8       Rdpack_0.11-0        lmtest_0.9-37       
## [118] data.table_1.12.6    bitops_1.0-6         gbRd_0.4-11         
## [121] httpuv_1.5.2         R6_2.4.1             latticeExtra_0.6-28 
## [124] promises_1.1.0       TSP_1.1-10           KernSmooth_2.23-15  
## [127] gridExtra_2.3        codetools_0.2-16     MASS_7.3-53         
## [130] gtools_3.8.1         assertthat_0.2.1     openssl_1.4.1       
## [133] withr_2.1.2          qlcMatrix_0.9.7      diptest_0.75-7      
## [136] doSNOW_1.0.18        grid_3.6.3           rpart_4.1-15        
## [139] tidyr_1.0.0          class_7.3-17         rmarkdown_2.5       
## [142] segmented_1.0-0      Rtsne_0.15           shiny_1.4.0         
## [145] snowfall_1.84-6.1    scatterplot3d_0.3-41 base64enc_0.1-3

  1. Institute of Psychiatry and Neuroscience of Paris, INSERM U1266, 75014, Paris, France

LS0tCnRpdGxlOiAiQ29tcGFyYWlzb24gb2YgVlAgYW5kIERQIGRlcml2ZWQgbmV1cm9ucyBkaWZmZXJlbnRpYXRpb24gdHJhamVjdG9yaWVzIgphdXRob3I6CiAgLSBNYXR0aGlldSBNb3JlYXVeW0luc3RpdHV0ZSBvZiBQc3ljaGlhdHJ5IGFuZCBOZXVyb3NjaWVuY2Ugb2YgUGFyaXMsIElOU0VSTSBVMTI2NiwgNzUwMTQsIFBhcmlzLCBGcmFuY2VdLCBtYXR0aGlldS5tb3JlYXVAaW5zZXJtLmZyCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVCLCAlWScpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OiAKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgZGZfcHJpbnQ6IHRpYmJsZQogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICBpbmNsdWRlczoKICAgICAgaW5faGVhZGVyOiBoZWFkZXIuaHRtbAogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA1CiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogeWVzCi0tLQoKYGBge2NzcywgZWNobz1GQUxTRX0KaDEgewogIGZvbnQtc2l6ZTogMzRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICNlNjRkMDA7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CmgxLnRpdGxlIHsKICBmb250LXNpemU6IDQwcHg7CiAgbWFyZ2luLXRvcDogMnJlbTsKICBtYXJnaW4tYm90dG9tOiAxcmVtOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDIgewogIGZvbnQtc2l6ZTogMzBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDMgewogIGZvbnQtc2l6ZTogMjRweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDQgewogIGZvbnQtc2l6ZTogMjBweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KaDUgewogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tdG9wOiAycmVtOwogIG1hcmdpbi1ib3R0b206IDFyZW07CiAgY29sb3I6ICMwMDAwMDA7Cn0KCi5zY3JvbGwtMTAwIHsKICBtYXgtaGVpZ2h0OiAyMDBweDsKICBvdmVyZmxvdy15OiBhdXRvOwogIGJhY2tncm91bmQtY29sb3I6IGluaGVyaXQ7Cn0KCnAgewogIGZvbnQtc2l6ZTogMTZweDsKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGZpZy5hbGlnbiA9ICdjZW50ZXInLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFKQpgYGAKCiMgTG9hZCBsaWJyYXJpZXMgYW5kIFFDRmlsdGVyZWQgZGF0YXNldAoKYGBge3IgfQojIExvYWQgbGlicmFyeQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShwcmluY3VydmUpCmxpYnJhcnkobW9ub2NsZSkKbGlicmFyeShGYXRlSUQpCmxpYnJhcnkocGFyYWxsZWwpCmxpYnJhcnkoc2VyaWF0aW9uKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShnZ0V4dHJhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkod2VzYW5kZXJzb24pCgojU2V0IGdncGxvdCB0aGVtZSBhcyBjbGFzc2ljCnRoZW1lX3NldCh0aGVtZV9jbGFzc2ljKCkpCmBgYAoKYGBge3J9CiMgTG9hZCB0aGUgZnVsbCBhbm5vdGF0ZWQgZGF0YXNldApBbGxjZWxscy5kYXRhIDwtIHJlYWRSRFMoIi4vQ2x1c3RlcmVkLmNlbGxzLlJEUyIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDgsIDYpfQpjb2xvcnMgPC0gIGMoIiM5Njk2OTYiLAogICAgICAgICAgICAgIHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiIzgzQzNCOCIsICIjMDA5RkRBIiwgIiMzRTY5QUMiLCAiI0U0NkI2QiIpKSwKICAgICAgICAgICAgICAiI2VjNzU2ZCIsICIjYzc3M2E3IiwgIiM3MjkzYzgiLCAiI2I3OWYwYiIsICIjM2NhNzNmIiwiIzMxYjZiZCIsCiAgICAgICAgICAgICAgIiNlYmNiMmUiLCAiIzllYzIyZiIsICIjYTk5NjFiIiwgIiNjYzNhMWIiLCAiI2NjODc3OCIgLCAiI2QxNGM4ZCIsICIjNGNhYmRjIiwgIiM1YWI3OTMiLCAiI2U3ODIzYSIsIiNlNmJiOWIiLCAiIzA0NmM5YSIsICIjNDc4NGEyIiAsICIjNDk5MGM5IikKCkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsIAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gMiwKICAgICAgICBuby5sZWdlbmQgPSBGLAogICAgICAgIGNvbHMudXNlID0gY29sb3JzKQpgYGAKCiMgUGFsbGlhbCB0cmFuc2l0aW9uIHN0YXRlIGNlbGxzCgojIyBFeHRyYWN0IGFwaWNhbCBwcm9nZW5pdG9ycwoKV2UgcGVyZm9ybSBLbWVhbnMgY2x1c3RlcmluZyBvbiB0aGUgNCBjZWxsIHN0YXRlIHNjb3JlcyA6CgotIFN1Yi1wYWxsaWFsIG5ldXJvbnMgYFNQYAotIFBhbGxpYWwgbmV1cm9ucyBgUGFsYAotIFN1Yi1wYWxsaWFsIEJQIGBTUC5CUGAKLSBQYWxsaWFsIEJQIGBQYWwuQlBgCgpgYGB7cn0KI0NhbGN1bGF0ZSBQYWxsaWFsIGFuZCBTdWItcGFsbGlhbCBCUCBzY29yZXMKUGFsLkJQLmdlbmVzIDwtIGMoIkVvbWVzIiwgIk5ldXJvZzIiLCAiTmV1cm9nMSIsICJQcm10OCIsICJOcnAxIikKZ2VuZXMubGlzdCA8LSBsaXN0KFBhbC5CUC5nZW5lcykKZW5yaWNoLm5hbWUgPC0gIlBhbC5CUF9zaWduYXR1cmUiCkFsbGNlbGxzLmRhdGEgPC0gQWRkTW9kdWxlU2NvcmUoQWxsY2VsbHMuZGF0YSwgZ2VuZXMubGlzdCA9IGdlbmVzLmxpc3QsIGdlbmVzLnBvb2wgPSBOVUxMLCBuLmJpbiA9IDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZC51c2UgPSAxLCBjdHJsLnNpemUgPSBsZW5ndGgoZ2VuZXMubGlzdCksIHVzZS5rID0gRkFMU0UsIGVucmljaC5uYW1lID0gZW5yaWNoLm5hbWUgLAogICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbS5zZWVkID0gMSkKCgpTUC5CUC5nZW5lcyA8LSBjKCJEbHgxIiwgIkRseDIiLCAiRGx4NSIsIkFzY2wxIiwgIkdzeDIiKQpnZW5lcy5saXN0IDwtIGxpc3QoU1AuQlAuZ2VuZXMpCmVucmljaC5uYW1lIDwtICJTUC5CUF9zaWduYXR1cmUiCkFsbGNlbGxzLmRhdGEgPC0gQWRkTW9kdWxlU2NvcmUoQWxsY2VsbHMuZGF0YSwgZ2VuZXMubGlzdCA9IGdlbmVzLmxpc3QsIGdlbmVzLnBvb2wgPSBOVUxMLCBuLmJpbiA9IDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZC51c2UgPSAxLCBjdHJsLnNpemUgPSBsZW5ndGgoZ2VuZXMubGlzdCksIHVzZS5rID0gRkFMU0UsIGVucmljaC5uYW1lID0gZW5yaWNoLm5hbWUgLAogICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbS5zZWVkID0gMSkKYGBgCgpgYGB7cn0Kc2V0LnNlZWQoMTAwKQojIFJ1biBLbWVhbnMgY2x1c3RlcmluZwpjbCA8LSBrbWVhbnMoY2JpbmQoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkU1Bfc2lnbmF0dXJlMSwKICAgICAgICAgICAgICAgICAgIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJFBhbF9zaWduYXR1cmUxLAogICAgICAgICAgICAgICAgICAgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkU1AuQlBfc2lnbmF0dXJlMSwKICAgICAgICAgICAgICAgICAgIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJFBhbC5CUF9zaWduYXR1cmUxKSwgNCkKCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJGttZWFuQ2x1c3QgPC0gcGFzdGUwKCJDbHVzdC4iLGNsJGNsdXN0ZXIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDUuMywgNCl9CmNvbC5wYWwgPC0gd2VzX3BhbGV0dGUoIkdyYW5kQnVkYXBlc3QxIiwgNCwgdHlwZSA9ICJkaXNjcmV0ZSIpCgpwMSA8LSBnZ3Bsb3QoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIGFlcyh4PVNQX3NpZ25hdHVyZTEsIHk9UGFsX3NpZ25hdHVyZTEsIGNvbG91ciA9IGttZWFuQ2x1c3QpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jb2wucGFsKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKZ2dNYXJnaW5hbChwMSwgdHlwZSA9ICJoaXN0b2dyYW0iLCBmaWxsPSJsaWdodGdyZXkiKQoKRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIGdyb3VwLmJ5ID0gImttZWFuQ2x1c3QiLAogICAgICAgIHJlZHVjdGlvbi51c2UgPSAic3ByaW5nIiwKICAgICAgICBjb2xzLnVzZSA9IGNvbC5wYWwsCiAgICAgICAgZGltLjEgPSAxLAogICAgICAgIGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSA0LAogICAgICAgIG5vLmxlZ2VuZCA9IEYpCmBgYAoKV2UgdGhlbiBleHRyYWN0IHRoZSBQYWxsaWFsIGNlbGxzIGJyYW5jaGUuIFdlIGFsc28gZXhjbHVkZXMgQ1IgY2VsbHMgY2x1c3RlciBmb3JtIHRoZSB0cmFqZWN0b3J5IGluZmVyZW5jZS4KCmBgYHtyfQojUmVtb3ZlIHRoZSBzdWItcGFsbGlhbCBjZWxscyBicmFuY2hlCk1lYW5LY2x1c3QuU1BzY29yZSA8LSBhZ2dyZWdhdGUoU1Bfc2lnbmF0dXJlMSB+IGttZWFuQ2x1c3QsIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhLCBtZWFuKQpTUGNsdXN0IDwtIE1lYW5LY2x1c3QuU1BzY29yZSAlPiUgZmlsdGVyKFNQX3NpZ25hdHVyZTEgPT0gbWF4KFNQX3NpZ25hdHVyZTEpKSAlPiUgcHVsbChrbWVhbkNsdXN0KQoKU1AuY2VsbHMgPC0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEgJT4lIGZpbHRlcihrbWVhbkNsdXN0ID09IFNQY2x1c3QpICU+JSBwdWxsKEJhcmNvZGVzKQoKIyBSZW1vdmUgY2VsbHMgbm90IHVzZSBmb3IgdHJhamVjdG9yeSBpbmZlcmVuY2UgKFN1YnBhbGxpYWwgY2VsbHMgZGVmaW5lZCBieSBrbWVhbnMsIExhdGUgR0FCQSBuZXVyb25zIGFuZCBDUiBjZWxscykKRXhjbHVkZWQuY2x1c3RlcnMgPC0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEgJT4lCiAgICAgICAgICAgICAgICAgIGZpbHRlcihDbHVzdGVyLmlkZW50ICVpbiUgZ3JlcCgiKlN1YnxHQUJBfExOLkdsdXQuMTN8TE4uR2x1dC4xNHxMTi5HbHV0LjEkIiwgdW5pcXVlKGFzLmNoYXJhY3RlcihBbGxjZWxscy5kYXRhQGlkZW50KSksIHZhbHVlID0gVCkpICU+JQogICAgICAgICAgICAgICAgICBwdWxsKEJhcmNvZGVzKSAKCiMgV2UgZnVydGhlciBrZWVwIG9ubHkgcGFsbGlhbCBhcGljYWwgcHJvZ2VuaXRvciBjbHVzdGVyIGFtb25nIG90aGVyIEFQIGNsdXN0ZXJzCk1lYW5LY2x1c3QuQVBzY29yZSA8LSBhZ2dyZWdhdGUoQVBfc2lnbmF0dXJlMSB+IGttZWFuQ2x1c3QsIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhLCBtZWFuKQpBUGNsdXN0IDwtIE1lYW5LY2x1c3QuQVBzY29yZSAlPiUgZmlsdGVyKEFQX3NpZ25hdHVyZTEgPT0gbWF4KEFQX3NpZ25hdHVyZTEpKSAlPiUgcHVsbChrbWVhbkNsdXN0KQoKQWxsLkFQIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhICU+JSBmaWx0ZXIoa21lYW5DbHVzdCA9PSBBUGNsdXN0KSAlPiUgcHVsbChCYXJjb2RlcykKVmFsaWRlLkFQIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhICU+JSBmaWx0ZXIoQ2x1c3Rlci5pZGVudCAlaW4lIGdyZXAoIkRvcnNhbC5QYWxsaXVtfGxhdGVyYWwuUGFsbGl1bS4xfGxhdGVyYWwuUGFsbGl1bS4yfFZlbnRyYWwuUGFsbGl1bSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXF1ZShhcy5jaGFyYWN0ZXIoQWxsY2VsbHMuZGF0YUBpZGVudCkpLCB2YWx1ZSA9IFQpKSAlPiUgcHVsbChCYXJjb2RlcykKCmZpbHRlcmVkLkFQIDwtIEFsbC5BUFshQWxsLkFQICVpbiUgVmFsaWRlLkFQXQoKI1JlbW92ZSBhbGwgaW52YWxpZGUgY2VsbHMgKyAzIHBhbGxpYWwgb3V0bGllciBjZWxscwpDZWxscy50by51c2UgPC0gcm93bmFtZXMoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEpWyFyb3duYW1lcyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSkgJWluJSB1bmlxdWUoYyhTUC5jZWxscywgRXhjbHVkZWQuY2x1c3RlcnMsIGZpbHRlcmVkLkFQLCBjKCJBVFRUQ1RHQ0FDR0dDQ0FUIiAsICJDQUFHVFRHQ0FBR0NDVEFUIiwgIkNUQUNBVFRHVEFHQ1RHQ0MiKSkpXQpBbGxjZWxscy5kYXRhIDwtIFN1YnNldERhdGEoQWxsY2VsbHMuZGF0YSwgY2VsbHMudXNlID0gQ2VsbHMudG8udXNlLCBzdWJzZXQucmF3ID0gVCwgIGRvLmNsZWFuID0gRikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOCwgNil9CmNvbG9ycyA8LSAgYygiIzk2OTY5NiIsCiAgICAgICAgICAgICAgdG9sb3dlcihjKCIjNjhCMDQxIiwgIiNFM0MxNDgiLCAiI0I3RDE3NCIsICIjRTQ2QjZCIikpLAogICAgICAgICAgICAgICIjY2MzYTFiIiwgIiNjYzg3NzgiICwgIiNkMTRjOGQiLCAiIzRjYWJkYyIsICIjNWFiNzkzIiwgIiNlNzgyM2EiLCIjZTZiYjliIiwgIiMwNDZjOWEiLCAiIzQ3ODRhMiIgLCAiIzQ5OTBjOSIpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLCAKICAgICAgICBkaW0uMSA9IDEsCiAgICAgICAgZGltLjIgPSAyLAogICAgICAgIGRvLmxhYmVsPVQsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDIsCiAgICAgICAgbm8ubGVnZW5kID0gVCwKICAgICAgICBjb2xzLnVzZSA9IGNvbG9ycykKYGBgCgojIyBGaWx0ZXIgdGhlIGdlbmUgY291bnRzIG1hdHJpeAoKYGBge3J9CiMgRmlsdGVyIGdlbmVzCm51bS5jZWxscyA8LSBNYXRyaXg6OnJvd1N1bXMoQWxsY2VsbHMuZGF0YUByYXcuZGF0YSA+IDApCmdlbmVzLnVzZSA8LSBuYW1lcyh4ID0gbnVtLmNlbGxzW3doaWNoKHggPSBudW0uY2VsbHMgPj0gMjApXSkKQWxsY2VsbHMuZGF0YUByYXcuZGF0YSA8LSBBbGxjZWxscy5kYXRhQHJhdy5kYXRhW2dlbmVzLnVzZSwgXQoKIyBOb3JtYWxpemF0aW9uIGFuZCB2YXJpYWJsZSBnZW5lIHNlbGVjdGlvbgpBbGxjZWxscy5kYXRhIDwtIE5vcm1hbGl6ZURhdGEob2JqZWN0ID0gQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUuZmFjdG9yID0gcm91bmQobWVkaWFuKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJG5VTUkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQoKQWxsY2VsbHMuZGF0YSA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBBbGxjZWxscy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BlcnNpb24uZnVuY3Rpb24gPSBMb2dWTVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeC5sb3cuY3V0b2ZmID0gMC4wMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4LmhpZ2guY3V0b2ZmID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5LmN1dG9mZiA9IDIsIGRvLnBsb3QgPSBGLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQpsZW5ndGgoQWxsY2VsbHMuZGF0YUB2YXIuZ2VuZXMpCmBgYAoKCmBgYHtyfQpybShsaXN0ID0gbHMoKVshbHMoKSAlaW4lICJBbGxjZWxscy5kYXRhIl0pCmBgYAoKIyBDb21wdXRlIGNlbGxzJyBmYXRlIGJpYXMgYWxvbmcgdHB3YXJkIGVhY2ggbWF0dXJlIG5ldXJvbmFsIHR5cGVzCgojIyBQcmVwYXJlIEZhdGVJRCBpbnB1dCBkYXRhCgpgYGB7cn0KIyBGYXRhSUQgcmVxdWllcmVzIHRoZSB0ZXJtaW5hbCBjbHVzdGVycyBJRCB0byBiZSBpbnRlZ2VycwpUZXJtaW5hbEZhdGVzIDwtIGdyZXAoIjE2fDI0fDIyfDE5fDI2fDIwfDIxIiwgdW5pcXVlKGFzLmNoYXJhY3RlcihBbGxjZWxscy5kYXRhQGlkZW50KSksIHZhbHVlID0gVCkKCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJE5ld0NsdXN0ZXJJRCA8LSBzYXBwbHkoYXMuY2hhcmFjdGVyKEFsbGNlbGxzLmRhdGFAaWRlbnQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIGlmKHggPT0gVGVybWluYWxGYXRlc1sxXSl7eD0xfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoeD09IFRlcm1pbmFsRmF0ZXNbMl0pe3g9Mn0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKHg9PSBUZXJtaW5hbEZhdGVzWzNdKXt4PTN9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZih4PT0gVGVybWluYWxGYXRlc1s0XSl7eD00fQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYoeD09IFRlcm1pbmFsRmF0ZXNbNV0pe3g9NX0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmKHg9PSBUZXJtaW5hbEZhdGVzWzZdKXt4PTZ9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZih4PT0gVGVybWluYWxGYXRlc1s3XSl7eD03fQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2V7eD14fSkKQWxsY2VsbHMuZGF0YSA8LSBTZXRBbGxJZGVudChBbGxjZWxscy5kYXRhLCBpZCA9ICJOZXdDbHVzdGVySUQiKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg4LCA2KX0KY29sb3JzIDwtICBjKCIjY2M4Nzc4IiAsICIjZDE0YzhkIiwgIiM0Y2FiZGMiLCAiIzVhYjc5MyIsICIjZTc4MjNhIiwiI2U2YmI5YiIsIiNjYzNhMWIiLAogICAgICAgICAgICAgIiM5Njk2OTYiLAogICAgICAgICAgICAgIHRvbG93ZXIoYygiIzY4QjA0MSIsICIjRTNDMTQ4IiwgIiNCN0QxNzQiLCAiI0U0NkI2QiIpKSwKICAgICAgICAgICAgICAiIzA0NmM5YSIsICIjNDc4NGEyIiAsICIjNDk5MGM5IikKCkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsIAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBuby5sZWdlbmQgPSBULAogICAgICAgIGNvbHMudXNlID0gY29sb3JzKQpgYGAKCldlIHJlc3RyaWN0ZWQgdGhlIGFuYWx5c2lzIHRvIHRoZSBtb3N0IHZhcmlhYmxlIGdlbmVzIGFzIGRlcnRlcm1pbmVkIGJ5IHRoZSBTZXVyYXQgZnVuY3Rpb24gIkZpbmRWYXJpYWJsZUdlbmVzIiBleGNsdWRpbmcgY2VsbCBjeWxjZSBwaGFzZSBnZW5lcwoKYGBge3J9CiMgRXhjbHVkZSBjZWxsIGN5Y2xlIGFzc29jaWF0ZWQgZ2VuZXMKQ0NnZW5lcyA8LSBhcy5jaGFyYWN0ZXIocmVhZC50YWJsZSgiLi9Qcm9nZW5pdG9ycy9DZWxsQ3ljbGVHZW5lcy5jc3YiLCBzZXAgPSAiXHQiLCBoZWFkZXIgPSBGKVssMV0pCklucHV0LmdlbmVzIDwtIEFsbGNlbGxzLmRhdGFAdmFyLmdlbmVzWyFBbGxjZWxscy5kYXRhQHZhci5nZW5lcyAlaW4lIENDZ2VuZXNdCgojIEZhdGVJRCByZXF1aWVyZXMgdGhlIGV4cHJlc3Npb24gbWF0cml4IHRvIGJlIGEgZGF0YWZyYW1lCk5vcm0uTWF0IDwtIGFzLmRhdGEuZnJhbWUoYXMubWF0cml4KEFsbGNlbGxzLmRhdGFAZGF0YVtyb3cubmFtZXMoQWxsY2VsbHMuZGF0YUBkYXRhKSAlaW4lIElucHV0LmdlbmVzLF0pKQoKIyBTZXQgYSBjbHVzdGVyIGFzc2lnbm1lbnQgZmFjdG9yIGZvciBlYWNoIGNlbGxzCkNsdXN0ZXJJZGVudCA8LSBhcy5jaGFyYWN0ZXIoQWxsY2VsbHMuZGF0YUBpZGVudCkKbmFtZXMoQ2x1c3RlcklkZW50KSA8LSBuYW1lcyhBbGxjZWxscy5kYXRhQGlkZW50KQoKIyBGaW5hbHkgRmF0ZUlEIHJlcXVpcmVzIHRvIHNwZWNpZnkgdGhlIGlkZW50aXR5IG9mIHRoZSBhdHRyYWN0b3Igc3RhdGUgY2x1c3RlcnMKQXR0cmFjdG9ycyA8LSAxOjcKYGBgCgojIyBDb21wdGUgdGhlIGNlbGxzJyBmYXRlIGJpYXMKCmBgYHtyIGNsYXNzLm91dHB1dD0ic2Nyb2xsLTEwMCJ9CkluZmVyZWQuRmF0ZS5iaWFzICA8LSBmYXRlQmlhcyhOb3JtLk1hdCwgQ2x1c3RlcklkZW50LCBBdHRyYWN0b3JzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeiA9IDEtY29yKE5vcm0uTWF0LCBtZXRob2QgPSAic3BlYXJtYW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbm5yPTEwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlubnJoPTMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRhcHQ9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZGVuY2U9MC45NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5iZmFjdG9yPTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2UuZGlzdD1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlZWQ9MTIzNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5idHJlZT1OVUxMKQpgYGAKIyMjIEluc3BlY3QgdGhlIHRyYWlubmluZyBzZXQgdXNlIGF0IGVhY2ggY2xhc3NpZmljYXRpb24gaXRlcmF0aW9uCmBgYHtyfQpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRGYXRlSUQuaXRlcmF0aW9uIDwtICIwIgpBbGxjZWxscy5kYXRhIDwtIFNldEFsbElkZW50KEFsbGNlbGxzLmRhdGEsIGlkID0gIkZhdGVJRC5pdGVyYXRpb24iKQoKZm9yIChpIGluIHNlcSgwLCBsZW5ndGgoSW5mZXJlZC5GYXRlLmJpYXMkcmZsKSwgYnkgPSA1KVstMV0pIHsKICBpdGVyIDwtIHNlcShpLTQsaSkKICBCYXJjb2RlcyA8LSBjKCkKICBmb3IgKGogaW4gaXRlcikgewogICAgQmFyY29kZXMgPC0gYyhCYXJjb2RlcywgbmFtZXMoSW5mZXJlZC5GYXRlLmJpYXMkcmZsW1tqXV0kcHJlZGljdGVkKSkKICB9CiAgQWxsY2VsbHMuZGF0YSA8LSBTZXRJZGVudChBbGxjZWxscy5kYXRhLCBjZWxscy51c2UgPSBCYXJjb2RlcywgaWRlbnQudXNlID0gcGFzdGUwKCJpdGVyICIsaXRlclsxXSwiIHRvICIsIGl0ZXJbNF0pKQp9CmBgYAoKCmBgYHtyIGZpZy5kaW09Yyg4LCA2KX0KY29sb3JzIDwtIGMoIiNkMTRjOGQiLCAiI2NjM2ExYiIsICIjMDQ2YzlhIiwgIiNlNzgyM2EiLCAiI2NjODc3OCIsICIjNjhiMDQxIiwgIiM1YWI3OTMiLCAiI2UzYzE0OCIsICIjZTQ2QjZiIiwgIiNiNzlmMGIiKQpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGRpbS4xID0gMSxkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICBuby5sZWdlbmQgPSBGLAogICAgICAgIGNvbHMudXNlID0gYygiI2RmZGZkZiIsIGNvbG9ycykpCmBgYAoKIyMjIEluc3BlY3QgdGhlIHRlc3Qgc2V0IHVzZSBhdCBjbGFzc2lmaWNhdGlvbiBpdGVyYXRpb24KYGBge3J9CkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJEZhdGVJRC5pdGVyYXRpb24gPC0gIjAiCkFsbGNlbGxzLmRhdGEgPC0gU2V0QWxsSWRlbnQoQWxsY2VsbHMuZGF0YSwgaWQgPSAiRmF0ZUlELml0ZXJhdGlvbiIpCgpmb3IgKGkgaW4gc2VxKDAsIGxlbmd0aChJbmZlcmVkLkZhdGUuYmlhcyRyZmwpLCBieSA9IDUpWy0xXSkgewogIGl0ZXIgPC0gc2VxKGktNCxpKQogIEJhcmNvZGVzIDwtIGMoKQogIGZvciAoaiBpbiBpdGVyKSB7CiAgICBCYXJjb2RlcyA8LSBjKEJhcmNvZGVzLCBuYW1lcyhJbmZlcmVkLkZhdGUuYmlhcyRyZmxbW2pdXSR0ZXN0JHByZWRpY3RlZCkpCiAgfQogIEFsbGNlbGxzLmRhdGEgPC0gU2V0SWRlbnQoQWxsY2VsbHMuZGF0YSwgY2VsbHMudXNlID0gQmFyY29kZXMsIGlkZW50LnVzZSA9IHBhc3RlMCgiaXRlciAiLGl0ZXJbMV0sIiB0byAiLCBpdGVyWzRdKSkKfQpgYGAKCgpgYGB7ciBmaWcuZGltPWMoOCwgNil9CkRpbVBsb3QoQWxsY2VsbHMuZGF0YSwKICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgZGltLjEgPSAxLGRpbS4yID0gMiwKICAgICAgICBkby5sYWJlbD1ULAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIG5vLmxlZ2VuZCA9IEYsCiAgICAgICAgY29scy51c2UgPSBjKCIjZGZkZmRmIiwgY29sb3JzKSkKCkFsbGNlbGxzLmRhdGEgPC0gU2V0QWxsSWRlbnQoQWxsY2VsbHMuZGF0YSwgaWQgPSAiQ2x1c3Rlci5pZGVudCIpCmBgYAoKIyMgSW1wb3J0IGxpbmVhZ2UgYmlhcyBpbnRvIFNldXJhdCBtZXRhLmRhdGEKCmBgYHtyfQpwcm9icyA8LSBJbmZlcmVkLkZhdGUuYmlhcyRwcm9ic1ssc2VxKGxlbmd0aChBdHRyYWN0b3JzKSldCgpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLk5yNGEyIDwtIHByb2JzJHQxCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuRm94cDJjIDwtIHByb2JzJHQyCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuUHBwMXIxNGMgPC0gcHJvYnMkdDMKQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5GZXpmMSA8LSBwcm9icyR0NApBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLkZveHAyYSA8LSBwcm9icyR0NQpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLkZveHAyYiA8LSBwcm9icyR0NgpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLk5maXggPC0gcHJvYnMkdDcKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSwgOSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gN0EgYW5kIFM3QSJ9CkZlYXR1cmVQbG90KG9iamVjdCA9IEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgIGZlYXR1cmVzLnBsb3QgPSBjKCJwcm9iLk5yNGEyIiwgInByb2IuTmZpeCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwcm9iLlBwcDFyMTRjIiwicHJvYi5GZXpmMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwcm9iLkZveHAyYSIsICJwcm9iLkZveHAyYiIsICJwcm9iLkZveHAyYyIpLAogICAgICAgICAgICBjb2xzLnVzZSA9IHJldihSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwobiA9IDExLCBuYW1lID0gIlNwZWN0cmFsIikpLAogICAgICAgICAgICByZWR1Y3Rpb24udXNlID0gInNwcmluZyIsCiAgICAgICAgICAgIG5vLmxlZ2VuZCA9IFQpCmBgYAoKIyBFeHRyYWN0IHRoZSBOcjRhMiBhbmQgTmZpeCAibGluZWFnZSIgY2VsbHMKCiMjIEZpbmQgY2VsbHMgd2l0aCBzdHJvbmcgYmlhc2UgdG93YXJkIE5yNGEyIG5ldXJvbnMKCmBgYHtyfQpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSROcjRhMi5iaWFzZSA8LSBpZmVsc2UoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5OcjRhMiA+IDAuNSAmIGFicyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLk5maXgtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTnI0YTIpID4gMC4yNSwgIk5yNGEyLmxpbmVhZ2UiLCAiT3RoZXIubGluZWFnZXMiICkKCnRhYmxlKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJE5yNGEyLmJpYXNlKQpgYGAKCgojIyBGaW5kIGNlbGxzIHdpdGggc3Ryb25nIGJpYXNlIHRvd2FyZCBOZml4IG5ldXJvbnMKCmBgYHtyfQpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSROZml4LmJpYXNlIDwtIGlmZWxzZShBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLk5maXggPiAwLjUgJiBhYnMoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5OZml4LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRwcm9iLk5yNGEyKSA+IDAuMjUsICJOZml4LmxpbmVhZ2UiLCAiT3RoZXIubGluZWFnZXMiICkKCnRhYmxlKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJE5maXguYmlhc2UpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDgsIDYpfQpOcjRhMiA8LSByb3duYW1lcyhzdWJzZXQoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEsIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJE5yNGEyLmJpYXNlID09ICJOcjRhMi5saW5lYWdlIikpCk5maXggPC0gcm93bmFtZXMoc3Vic2V0KEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhLCBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSROZml4LmJpYXNlID09ICJOZml4LmxpbmVhZ2UiKSkKCgpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRsaW5lYWdlLmJpYXMgPC0gc2FwcGx5KEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJEJhcmNvZGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIGlmKHggJWluJSBOcjRhMil7eD0iTnI0YTIubGluZWFnZSJ9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZih4ICVpbiUgTmZpeCApe3g9ICJOZml4LmxpbmVhZ2UifQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2V7eD0gIk5vdC5hc3NpZ25lZCJ9KQoKRGltUGxvdChBbGxjZWxscy5kYXRhLAogICAgICAgIGdyb3VwLmJ5ID0gImxpbmVhZ2UuYmlhcyIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNjYzM5MWIiLCIjOTY5Njk2IiwiIzAyNmM5YSIpLAogICAgICAgIG5vLmxlZ2VuZCA9IEYpCmBgYAoKIyMgSW5zcGVjdCBmYXRlIGJpYXMgYW1vbmcgQVBzCgpgYGB7cn0KIyBGYXRlIGJpYXNlIGluIHByb2dlbml0b3IgZG9tYWluZXMKZGF0YSA8LSBtZWx0KGRhdGEuZnJhbWUoQ2x1c3RlcnMgPSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRDbHVzdGVyLmlkZW50LAogICAgICAgICAgICAgICAgICAgICAgICBOZml4LnNjb3JlID0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkcHJvYi5OZml4LAogICAgICAgICAgICAgICAgICAgICAgICBOcjRhMi5zY29yZSA9IEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJHByb2IuTnI0YTIpKQoKY29sbmFtZXMoZGF0YSkgPC0gYygiQ2x1c3RlcnMiLCAibGluZWFnZSIsICJTY29yZSIpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDYsIDQuNSl9CmRhdGEgJT4lCiAgICAgZmlsdGVyKENsdXN0ZXJzICVpbiUgYygiQVAuVmVudHJhbC5QYWxsaXVtIiwgIkFQLmxhdGVyYWwuUGFsbGl1bS4xIiwgIkFQLmxhdGVyYWwuUGFsbGl1bS4yIiwgIkFQLkRvcnNhbC5QYWxsaXVtIikpICU+JQogICAgIG11dGF0ZShDbHVzdGVycyA9IGZhY3RvcihDbHVzdGVycywgbGV2ZWxzID1jKCJBUC5WZW50cmFsLlBhbGxpdW0iLCAiQVAubGF0ZXJhbC5QYWxsaXVtLjEiLCAiQVAubGF0ZXJhbC5QYWxsaXVtLjIiLCAiQVAuRG9yc2FsLlBhbGxpdW0iKSkpICU+JQogICAgIGdncGxvdChhZXMoeD1mYWN0b3IobGluZWFnZSwgbGV2ZWxzID0gYygiTnI0YTIuc2NvcmUiLCAiTmZpeC5zY29yZSIpICksIHk9U2NvcmUsIGZpbGw9IENsdXN0ZXJzKSkgKyAKICAgICAgICBnZW9tX2JveHBsb3Qobm90Y2g9VFJVRSkgKwogICAgICAgIGdlb21fcG9pbnQocG9zaXRpb249cG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4yKSwgc2l6ZSA9IC41LCBhZXMoZ3JvdXA9Q2x1c3RlcnMpKSArCiAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPSBjKCIjNjhiMDQxIiwgIiNlM2MxNDgiLCAiI2I3ZDE3NCIsICIjZTQ2YjZiIikpICArCiAgICAgICAgeGxhYigiIikKYGBgCgojIyBFeHRyYWN0IE5yNGEyIGFuZCBOZml4IGJpYXNlZCBjZWxscwoKYGBge3IgZmlnLmRpbT1jKDgsIDYpfQojU3Vic2V0IGRhdGFzZXQgdG8ga2VlcCBvbmx5IGNlbGxzIHdoaWNoIHNob3dlZCBzdWZmaWNpZW50IGRpZmZlcmVuY2Ugb2YgZmF0ZSBwcm9iYWJpbGl0eQpWUC5EUC5saW5lYWdlLmNlbGxzIDwtIGMocm93bmFtZXMoc3Vic2V0KEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhLCBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSROcjRhMi5iaWFzZSA9PSAiTnI0YTIubGluZWFnZSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHN1YnNldChBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSwgQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkTmZpeC5iaWFzZSA9PSAiTmZpeC5saW5lYWdlIikpKQoKCiMgV2UgZnVydGhlciBvbmx5IHJldGFpbiBWUCBhbmQgRFAgIHByb2dlbml0b3IgY2x1c3RlcnMKQWxsY2VsbHMuZGF0YSA8LSBTdWJzZXREYXRhKEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxscy51c2UgPSBWUC5EUC5saW5lYWdlLmNlbGxzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRlbnQucmVtb3ZlID0gYygiQVAubGF0ZXJhbC5QYWxsaXVtLjEiLCAiQVAubGF0ZXJhbC5QYWxsaXVtLjIiKSAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJzZXQucmF3ID0gVCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvLmNsZWFuID0gRikKCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBsYWJlbC5zaXplID0gNCwKICAgICAgICBjb2xzLnVzZSA9IGMoICIjZGZkZmRmIiwiIzY4YjA0MSIsICIjZTQ2YjZiIiwiI2NjM2ExYiIsIiNjYzg3NzgiLCIjZTZiYjliIiAsIiMwNDZjOWEiLCIjNDc4NGEyIiksCiAgICAgICAgbm8ubGVnZW5kID0gVCkKYGBgCgpgYGB7ciBmaWcuZGltPWMoOCwgNiksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gN0IifQpBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRMaW5lYWdlIDwtIGlmZWxzZShBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSROcjRhMi5iaWFzZSA9PSAiTnI0YTIubGluZWFnZSIsICJOcjRhMi5saW5lYWdlIiwgIk5maXgubGluZWFnZSIpCgpEaW1QbG90KEFsbGNlbGxzLmRhdGEsCiAgICAgICAgZ3JvdXAuYnkgPSAiTGluZWFnZSIsCiAgICAgICAgcmVkdWN0aW9uLnVzZSA9ICJzcHJpbmciLAogICAgICAgIGRpbS4xID0gMSwKICAgICAgICBkaW0uMiA9IDIsCiAgICAgICAgZG8ubGFiZWw9VCwKICAgICAgICBjb2xzLnVzZSA9IGMoIiNjYzM5MWIiLCIjMDI2YzlhIiksCiAgICAgICAgbGFiZWwuc2l6ZSA9IDQsCiAgICAgICAgbm8ubGVnZW5kID0gRikKYGBgCgpgYGB7cn0Kcm0obGlzdCA9IGxzKClbIWxzKCkgJWluJSBjKCJBbGxjZWxscy5kYXRhIildKQpgYGAKCiMgQWxpZ25lIGNlbGxzIGFsb25nIFBzZXVkb3RpbWUKCldlIGRlY2lkZWQgdG8gdXNlIHNwcmluZyBzcGFjZSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gdG8gZml0IHRoZSBwcmluY2lwYWxlIGN1cnZlIGJlY2F1c2UgaXQgaGFzIGJlZW4gY2FsY3VsYXRlZCBvbiBhbGwgY2VsbHMgdG9nZXRoZXIuIFRodXMgcmVmbGVjdGluZyBwYW4gbmV1cm9uYWwgZGlmZmVyZW50aWF0aW9uIGF4aXMgb2YgdmFyYXRpb24uCgojIyBOcjRhMiBuZXVyb25zIFBzZXVkb3RpbWUgb3JkZXJpbmcKCmBgYHtyfQpOcjRhMi5saW5lYWdlLmNlbGxzIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhICU+JQogICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihMaW5lYWdlID09ICJOcjRhMi5saW5lYWdlIikgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgcHVsbChCYXJjb2RlcykKCiMjIEZpdCBwcmluY2lwYWxlIGN1cnZlIG9uIHRoZSBkYXRhIGluIHRoZSBzcHJpbmcgc3BhY2UKZGF0YS5OcjRhMiA8LSBhcy5kYXRhLmZyYW1lKEFsbGNlbGxzLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1tOcjRhMi5saW5lYWdlLmNlbGxzLDE6Ml0pCgpmaXQgPC0gcHJpbmNpcGFsX2N1cnZlKGFzLm1hdHJpeChkYXRhLk5yNGEyWywxOjJdKSwKICAgICAgICAgICAgICAgICAgICAgICBzbW9vdGhlcj0nc21vb3RoX3NwbGluZScsCiAgICAgICAgICAgICAgICAgICAgICAgdHJhY2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJldGNoPTIpCgpOcjRhMi5wYy5saW5lIDwtIGFzLmRhdGEuZnJhbWUoZml0JHNbb3JkZXIoZml0JGxhbWJkYSksXSkgI1RoZSBwcmluY2lwYWwgY3VydmUgc21vb3RoZWQKZGF0YS5OcjRhMiRQc2V1ZG90aW1lU2NvcmUgPC0gZml0JGxhbWJkYS9tYXgoZml0JGxhbWJkYSkKCmRhdGEuTnI0YTIkQ2x1c3RlciA8LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSAlPiUKICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoTGluZWFnZSA9PSAiTnI0YTIubGluZWFnZSIpICU+JQogICAgICAgICAgICAgICAgICAgICAgIHB1bGwoTmV3Q2x1c3RlcklEKQoKIyBEaXJlY3Rpb24gb2YgdGhlIG1hdHVyYXRpb24gc2NvcmUgdXNpbmcgTmVzIGV4cHJlc3Npb24gKHJldmVydGUgaWYgcG9zaXRpdmUgY29ycmVsYXRpb24pCmlmIChjb3IoZGF0YS5OcjRhMiRQc2V1ZG90aW1lU2NvcmUsIEFsbGNlbGxzLmRhdGFAZGF0YVsnSG1nYTInLCBOcjRhMi5saW5lYWdlLmNlbGxzXSkgPiAwKSB7CiAgZGF0YS5OcjRhMiRQc2V1ZG90aW1lU2NvcmUgPC0gLShkYXRhLk5yNGEyJFBzZXVkb3RpbWVTY29yZSAtIG1heChkYXRhLk5yNGEyJFBzZXVkb3RpbWVTY29yZSkpCn0KYGBgCgojIyBOZml4IG5ldXJvbnMgUHNldWRvdGltZSBvcmRlcmluZwoKYGBge3J9Ck5maXgubGluZWFnZS5jZWxscyA8LSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSAlPiUKICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihMaW5lYWdlID09ICJOZml4LmxpbmVhZ2UiKSAlPiUKICAgICAgICAgICAgICAgICAgICAgIHB1bGwoQmFyY29kZXMpCgojIyBGaXQgcHJpbmNpcGFsZSBjdXJ2ZSBvbiB0aGUgZGF0YSBpbiB0aGUgc3ByaW5nIHNwYWNlCmRhdGEuTmZpeCA8LSBhcy5kYXRhLmZyYW1lKEFsbGNlbGxzLmRhdGFAZHIkc3ByaW5nQGNlbGwuZW1iZWRkaW5nc1tOZml4LmxpbmVhZ2UuY2VsbHMsMToyXSkKCmZpdCA8LSBwcmluY2lwYWxfY3VydmUoYXMubWF0cml4KGRhdGEuTmZpeFssMToyXSksCiAgICAgICAgICAgICAgICAgICAgICAgc21vb3RoZXI9J3Ntb290aF9zcGxpbmUnLAogICAgICAgICAgICAgICAgICAgICAgIHRyYWNlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyZXRjaD0yKQoKTmZpeC5wYy5saW5lIDwtIGFzLmRhdGEuZnJhbWUoZml0JHNbb3JkZXIoZml0JGxhbWJkYSksXSkgI1RoZSBwcmluY2lwYWwgY3VydmUgc21vb3RoZWQKZGF0YS5OZml4JFBzZXVkb3RpbWVTY29yZSA8LSBmaXQkbGFtYmRhL21heChmaXQkbGFtYmRhKQoKZGF0YS5OZml4JENsdXN0ZXIgPC0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEgJT4lCiAgICAgICAgICAgICAgICAgICAgIGZpbHRlcihMaW5lYWdlID09ICJOZml4LmxpbmVhZ2UiKSAlPiUKICAgICAgICAgICAgICAgICAgICAgcHVsbChOZXdDbHVzdGVySUQpCgoKIyBEaXJlY3Rpb24gb2YgdGhlIG1hdHVyYXRpb24gc2NvcmUgdXNpbmcgTmVzIGV4cHJlc3Npb24gKHJldmVydGUgaWYgcG9zaXRpdmUgY29ycmVsYXRpb24pCmlmIChjb3IoZGF0YS5OZml4JFBzZXVkb3RpbWVTY29yZSwgQWxsY2VsbHMuZGF0YUBkYXRhWydIbWdhMicsIE5maXgubGluZWFnZS5jZWxsc10pID4gMCkgewogIGRhdGEuTmZpeCRQc2V1ZG90aW1lU2NvcmUgPC0gLShkYXRhLk5maXgkUHNldWRvdGltZVNjb3JlIC0gbWF4KGRhdGEuTmZpeCRQc2V1ZG90aW1lU2NvcmUpKQp9CmBgYAoKIyMgQ29tYmluZSBib3RoIHRyYWplY3Rvcnkgb3JkZXJpbmcKCmBgYHtyfQpQc2V1ZG90aW1lIDwtIHJiaW5kKGRhdGEuTnI0YTIgJT4lIGRwbHlyOjpzZWxlY3QoUHNldWRvdGltZVNjb3JlKSwKICAgICAgICAgICAgICAgICAgICBkYXRhLk5maXggJT4lIGRwbHlyOjpzZWxlY3QoUHNldWRvdGltZVNjb3JlKSkKCkFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJFBzZXVkb3RpbWUgPC0gUHNldWRvdGltZVtyb3duYW1lcyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSksXQpgYGAKCgpgYGB7ciBmaWcuZGltPWMoOCwgNil9CiNQbG90IFBzZXVkb3RpbWUgc2NvcmUgd2l0aCB0aGUgMiBwcmluY2lwYWwgY3VydmVzCmRhdGEgPC0gYXMuZGF0YS5mcmFtZShBbGxjZWxscy5kYXRhQGRyJHNwcmluZ0BjZWxsLmVtYmVkZGluZ3NbLDE6Ml0pCmRhdGEkUHNldWRvdGltZVNjb3JlIDwtIEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJFBzZXVkb3RpbWUKCmNvbHMgPC0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKG4gPTExLCBuYW1lID0gIlNwZWN0cmFsIikpKDEwMCkKCmdncGxvdChkYXRhLCBhZXMoc3ByaW5nMSwgc3ByaW5nMikpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvcj1Qc2V1ZG90aW1lU2NvcmUpLCBzaXplPTIsIHNoYXBlPTE2KSArIAogIHNjYWxlX2NvbG9yX2dyYWRpZW50bihjb2xvdXJzPXJldihjb2xzKSwgbmFtZT0nU3BldWRvdGltZSBzY29yZScpICsKICBnZW9tX2xpbmUoZGF0YT1OZml4LnBjLmxpbmUsIGNvbG9yPSIjY2MzOTFiIiwgc2l6ZT0wLjc3KSArCiAgZ2VvbV9saW5lKGRhdGE9TnI0YTIucGMubGluZSwgY29sb3I9IiMwMjZjOWEiLCBzaXplPTAuNzcpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiQWxsY2VsbHMuZGF0YSIpXSkKYGBgCgoKIyBGaW5kIERFRyBiZXR3ZWVuIHRoZSB0d28gdHJhamVjdG9yaWVzIGFuZCBhbG9uZyB0aGUgcHNldWRvdGltZSAKCiMjIEZpbHRlciBnZW5lIGNvdW50cyBtYXRyaXgKYGBge3J9CiNGaWx0ZXIgZ2VuZXMKbnVtLmNlbGxzIDwtIE1hdHJpeDo6cm93U3VtcyhBbGxjZWxscy5kYXRhQHJhdy5kYXRhID4gMCkKZ2VuZXMudXNlIDwtIG5hbWVzKHggPSBudW0uY2VsbHNbbnVtLmNlbGxzID49IDEwXSkKQWxsY2VsbHMuZGF0YUByYXcuZGF0YSA8LSBBbGxjZWxscy5kYXRhQHJhdy5kYXRhW2dlbmVzLnVzZSwgXQoKIyBOb3JtYWxpemF0aW9uIGFuZCB2YXJpYWJsZSBnZW5lIHNlbGVjdGlvbgpBbGxjZWxscy5kYXRhIDwtIE5vcm1hbGl6ZURhdGEob2JqZWN0ID0gQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUuZmFjdG9yID0gcm91bmQobWVkaWFuKEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJG5VTUkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXkucHJvZ3Jlc3MgPSBGKQoKQWxsY2VsbHMuZGF0YSA8LSBGaW5kVmFyaWFibGVHZW5lcyhvYmplY3QgPSBBbGxjZWxscy5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW4uZnVuY3Rpb24gPSBFeHBNZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BlcnNpb24uZnVuY3Rpb24gPSBMb2dWTVIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeC5sb3cuY3V0b2ZmID0gMC4wMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4LmhpZ2guY3V0b2ZmID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5LmN1dG9mZiA9IDEuMywgZG8ucGxvdCA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheS5wcm9ncmVzcyA9IEYpCmxlbmd0aChBbGxjZWxscy5kYXRhQHZhci5nZW5lcykKYGBgCgojIyBJbml0aWFsaXplIGEgbW9ub2NsZSBvYmplY3QKCmBgYHtyfQojIFRyYW5zZmVydCBtZXRhZGF0YQptZXRhLmRhdGEgPC0gZGF0YS5mcmFtZShiYXJjb2RlID0gcm93bmFtZXMoQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICBDbHVzdGVyID0gQWxsY2VsbHMuZGF0YUBtZXRhLmRhdGEkQ2x1c3Rlci5pZGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgTGluZWFnZSA9IEFsbGNlbGxzLmRhdGFAbWV0YS5kYXRhJExpbmVhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgIFBzZXVkb3RpbWUuU2NvcmUgPSBBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSRQc2V1ZG90aW1lLAogICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSByb3duYW1lcyhBbGxjZWxscy5kYXRhQG1ldGEuZGF0YSkpCgpBbm5vdC5kYXRhICA8LSBuZXcoJ0Fubm90YXRlZERhdGFGcmFtZScsIGRhdGEgPSBtZXRhLmRhdGEpCgojIFRyYW5zZmVydCBjb3VudCBkYXRhCmNvdW50LmRhdGEgPSBkYXRhLmZyYW1lKGdlbmVfc2hvcnRfbmFtZSA9IHJvd25hbWVzKEFsbGNlbGxzLmRhdGFAcmF3LmRhdGEpLAogICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSByb3duYW1lcyhBbGxjZWxscy5kYXRhQHJhdy5kYXRhKSkKCmZlYXR1cmUuZGF0YSA8LSBuZXcoJ0Fubm90YXRlZERhdGFGcmFtZScsIGRhdGEgPSBjb3VudC5kYXRhKQoKIyBDcmVhdGUgdGhlIENlbGxEYXRhU2V0IG9iamVjdApnYm1fY2RzIDwtIG5ld0NlbGxEYXRhU2V0KGFzLm1hdHJpeChBbGxjZWxscy5kYXRhQHJhdy5kYXRhKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwaGVub0RhdGEgPSBBbm5vdC5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXR1cmVEYXRhID0gZmVhdHVyZS5kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxvd2VyRGV0ZWN0aW9uTGltaXQgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25GYW1pbHkgPSBuZWdiaW5vbWlhbCgpKQpgYGAKCmBgYHtyfQpnYm1fY2RzIDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoZ2JtX2NkcykKZ2JtX2NkcyA8LSBlc3RpbWF0ZURpc3BlcnNpb25zKGdibV9jZHMpCmdibV9jZHMgPC0gZGV0ZWN0R2VuZXMoZ2JtX2NkcywgbWluX2V4cHIgPSAwLjEpCmBgYAoKYGBge3J9CnJtKGxpc3QgPSBscygpWyFscygpICVpbiUgYygiQWxsY2VsbHMuZGF0YSIsICJnYm1fY2RzIildKQpgYGAKCiMjIFRlc3QgZWFjaCBnZW5lIHRyZW5kIG92ZXIgcHNldWRvdGltZSBzY29yZQoKYGBge3J9CiMgRXhjbHVkZSBjZWxsIGN5Y2xlIGFzc29jaWF0ZWQgZ2VuZXMKQ0NnZW5lcyA8LSBhcy5jaGFyYWN0ZXIocmVhZC50YWJsZSgiLi9Qcm9nZW5pdG9ycy9DZWxsQ3ljbGVHZW5lcy5jc3YiLCBzZXAgPSAiXHQiLCBoZWFkZXIgPSBGKVssMV0pCklucHV0LmdlbmVzIDwtIEFsbGNlbGxzLmRhdGFAdmFyLmdlbmVzWyFBbGxjZWxscy5kYXRhQHZhci5nZW5lcyAlaW4lIENDZ2VuZXNdCmBgYAoKYGBge3J9ClNwZXVkb3RpbWUubGluZWFnZXMuZGlmZiA8LSBkaWZmZXJlbnRpYWxHZW5lVGVzdChnYm1fY2RzW0lucHV0LmdlbmVzLF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbE1vZGVsRm9ybXVsYVN0ciA9ICJ+c20ubnMoUHNldWRvdGltZS5TY29yZSwgZGYgPSAzKSpMaW5lYWdlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWR1Y2VkTW9kZWxGb3JtdWxhU3RyID0gIn5zbS5ucyhQc2V1ZG90aW1lLlNjb3JlLCBkZiA9IDMpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JlcyA9IGRldGVjdENvcmVzKCkgLSAyKQoKI0ZpbHRlciBiYXNlZCBvbiBGRFIKU3BldWRvdGltZS5saW5lYWdlcy5kaWZmLmZpbHRlcmVkIDwtIFNwZXVkb3RpbWUubGluZWFnZXMuZGlmZiAlPiUgZmlsdGVyKHF2YWwgPCA1ZS0yKQpgYGAKCiMjIEZpbmQgZGlyZWN0aW9uIG9mIHRoZSBERUcKCldlIGZpbmQgZGlyZWN0aW9uIG9mIHRoZSBERUcgYnkgY2FsY3VsYXRpbmcgdGhlIGFyZWEgYmV0d2VlbiBjdXJ2ZXMgKEFCQykgZm9yIGJyYW5jaC1kZXBlbmRlbnQgZ2VuZXMgYnkgYWRhcHRpbmcgdGhlIG1vbm9jbGUgcGFja2FnZSBmdW5jdGlvbiBgY2FsQUJDc2AuIEdlbmVzIHNwZWNpZmljIEFCQyBpcyBjb21wdXRlZCBvbiBzbW9vdGhlZCBleHByZXNzaW9uIHZhbHVlIG92ZXIgMTAwIHBvaW50cyBhbG9uZyB0aGUgcHNldWRvdGltZQkKCiMjIyBTbW9vdGggZ2VuZSBleHByZXNzaW9uIGFsb25nIHBzZXVkb3RpbWUgCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBwc2V1ZG8tRFYgdmVjdG9yIG9mIDUwMCBwb2ludHMKblBvaW50cyA8LSAxMDAKCm5ld19kYXRhID0gbGlzdCgpCmZvciAoTGluZWFnZSBpbiB1bmlxdWUocERhdGEoZ2JtX2NkcykkTGluZWFnZSkpewogIG5ld19kYXRhW1tsZW5ndGgobmV3X2RhdGEpICsgMV1dID0gZGF0YS5mcmFtZShQc2V1ZG90aW1lLlNjb3JlID0gc2VxKG1pbihwRGF0YShnYm1fY2RzKSRQc2V1ZG90aW1lLlNjb3JlKSwgbWF4KHBEYXRhKGdibV9jZHMpJFBzZXVkb3RpbWUuU2NvcmUpLCBsZW5ndGgub3V0ID0gblBvaW50cyksIExpbmVhZ2U9TGluZWFnZSkKfQoKbmV3X2RhdGEgPSBkby5jYWxsKHJiaW5kLCBuZXdfZGF0YSkKCiMgU21vb3RoIGdlbmUgZXhwcmVzc2lvbgpjdXJ2ZV9tYXRyaXggPC0gZ2VuU21vb3RoQ3VydmVzKGdibV9jZHNbYXMuY2hhcmFjdGVyKFNwZXVkb3RpbWUubGluZWFnZXMuZGlmZi5maWx0ZXJlZCRnZW5lX3Nob3J0X25hbWUpLF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJlbmRfZm9ybXVsYSA9ICJ+c20ubnMoUHNldWRvdGltZS5TY29yZSwgZGYgPSAzKSpMaW5lYWdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWxhdGl2ZV9leHByID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfZGF0YSA9IG5ld19kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcmVzPSBkZXRlY3RDb3JlcygpIC0gMikKYGBgCgojIyMgQ29tcHV0ZSB0aGUgQUJDIGZvciBlYWNoIGdlbmVzCmBgYHtyfQojIEV4dHJhY3QgbWF0cml4IGNvbnRhaW5pbmcgU21vb3RoIGN1cnZlcyBmb3IgZWFjaCBsaW5lYWdlcwpOcjRhMl9jdXJ2ZV9tYXRyaXggPC0gY3VydmVfbWF0cml4WywgMTpuUG9pbnRzXSAjIHRoZSBmaXJzdCAxMDAgcG9pbnRzIGNvcnJlc3BvbmQgdG8gTnI0YTIgY2VsbHMKTmZpeF9jdXJ2ZV9tYXRyaXggPC0gY3VydmVfbWF0cml4WywgKG5Qb2ludHMgKyAxKTooMiAqIG5Qb2ludHMpXQogIApBQkNzX3JlcyA8LSBOcjRhMl9jdXJ2ZV9tYXRyaXggLSBOZml4X2N1cnZlX21hdHJpeCAjIERpcmVjdGlvbiBvZiB0aGUgY29tcGFyaXNvbiA6IHBvc3RpdmUgQUJDcyA8PT4gVXByZWd1bGF0ZWQgaW4gTnI0YTIgbGluZWFnZQpJTFJfcmVzIDwtIGxvZzIoTnI0YTJfY3VydmVfbWF0cml4LyAoTmZpeF9jdXJ2ZV9tYXRyaXggKyAwLjEpKSAjIEF2ZXJhZ2UgbG9nRkMgYmV0d2VlbiB0aGUgMiBjdXJ2ZXMKICAKQUJDc19yZXMgPC0gYXBwbHkoQUJDc19yZXMsIDEsIGZ1bmN0aW9uKHgsIG5Qb2ludHMpIHsKICAgICAgICAgICAgICAgICAgYXZnX2RlbHRhX3ggPC0gKHhbMTooblBvaW50cyAtIDEpXSArIHhbMjooblBvaW50cyldKS8yCiAgICAgICAgICAgICAgICAgIHN0ZXAgPC0gKDEwMC8oblBvaW50cyAtIDEpKQogICAgICAgICAgICAgICAgICByZXMgPC0gcm91bmQoc3VtKGF2Z19kZWx0YV94ICogc3RlcCksIDMpCiAgICAgICAgICAgICAgICAgIHJldHVybihyZXMpfSwKICAgICAgICAgICAgICAgICAgblBvaW50cyA9IG5Qb2ludHMpICMgQ29tcHV0ZSB0aGUgYXJlYSBiZWxvdyB0aGUgY3VydmUKICAKQUJDc19yZXMgPC0gY2JpbmQoQUJDc19yZXMsIElMUl9yZXNbLG5jb2woSUxSX3JlcyldKQpjb2xuYW1lcyhBQkNzX3Jlcyk8LSBjKCJBQkNzIiwgIkVuZHBvaW50X0lMUiIpCgojIEltcG9ydCBBQkMgdmFsdWVzIGludG8gdGhlIERFIHRlc3QgcmVzdWx0cyB0YWJsZQpTcGV1ZG90aW1lLmxpbmVhZ2VzLmRpZmYuZmlsdGVyZWQgPC0gY2JpbmQoU3BldWRvdGltZS5saW5lYWdlcy5kaWZmLmZpbHRlcmVkWywxOjRdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQUJDc19yZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTcGV1ZG90aW1lLmxpbmVhZ2VzLmRpZmYuZmlsdGVyZWRbLDU6Nl0pCmBgYAoKIyBDbHVzdGVyIGdlbmVzIGJ5IGV4cHJlc3Npb24gcHJvZmlsZXMgYWxvbmcgdGhlIHR3byB0cmFqZWN0b3JpZXMKCiMjIE5yNGEyIG5ldXJvbnMgc3BlY2lmaWMgdHJhbnNjcmlwdGlvbmFsIHRyYWplY3RvcmllcwoKYGBge3J9CiMgRXh0cmFjdCBOcjRhMiBuZXVyb25zIHRyYWplY3RvcnkgZ2VuZXMKTnI0YTIucmVzIDwtIGFzLmRhdGEuZnJhbWUoU3BldWRvdGltZS5saW5lYWdlcy5kaWZmLmZpbHRlcmVkW1NwZXVkb3RpbWUubGluZWFnZXMuZGlmZi5maWx0ZXJlZCRBQkNzID4gMCxdKQpOcjRhMi5nZW5lcyA8LSByb3cubmFtZXMoTnI0YTIucmVzKQpOcjRhMl9jdXJ2ZV9tYXRyaXggPC0gTnI0YTJfY3VydmVfbWF0cml4W3Jvd25hbWVzKE5yNGEyX2N1cnZlX21hdHJpeCkgJWluJSBOcjRhMi5nZW5lcywgXQpgYGAKCmBgYHtyfQojIEdyb3VwZSBnZW5lcyBpbiA2IGNsdXN0ZXJzIGJ5IHBhcnRpdGlvbmluZyByb3VuZCBtZWRvaWRzCk5yNGEyLmdlbmVzLmNsdXN0ZXJzIDwtIGNsdXN0ZXI6OnBhbShhcy5kaXN0KCgxIC0gY29yKHQoTnI0YTJfY3VydmVfbWF0cml4KSwgbWV0aG9kID0gInBlYXJzb24iKSkpLCBrPTYpCgojIENyZWF0ZSBhIGRhdGFmcmFtZSBzdG9yaW5nIERFRyB0ZXN0IGFuZCBjbHVzdGVyaW5nIHJlc3VsdHMKTnI0YTIuR2VuZS5keW5hbWlxdWUgPC0gZGF0YS5mcmFtZShHZW5lPSBuYW1lcyhOcjRhMi5nZW5lcy5jbHVzdGVycyRjbHVzdGVyaW5nKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdmFsPU5yNGEyLnJlcyRwdmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF2YWw9TnI0YTIucmVzJHF2YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQUJDcz1OcjRhMi5yZXMkQUJDcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBHZW5lLkNsdXN0ZXJzPSBwYXN0ZTAoIkNsdXN0LiIsIE5yNGEyLmdlbmVzLmNsdXN0ZXJzJGNsdXN0ZXJpbmcpKSAlPiUgYXJyYW5nZShHZW5lLkNsdXN0ZXJzKQoKcm93Lm5hbWVzKE5yNGEyLkdlbmUuZHluYW1pcXVlKSA8LSBOcjRhMi5HZW5lLmR5bmFtaXF1ZSRHZW5lCgp3cml0ZS50YWJsZShOcjRhMi5HZW5lLmR5bmFtaXF1ZSwgIi4vTnI0YTIuR2VuZS5keW5hbWlxdWUuY3N2Iiwgc2VwPSI7IikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSwgNSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gN0QifQojIE9yZGVyIHRoZSByb3cgdXNpbmcgc2VyaWF0aW9uCmRzdCA8LSBhcy5kaXN0KCgxLWNvcihzY2FsZSh0KE5yNGEyX2N1cnZlX21hdHJpeCkpLCBtZXRob2QgPSAicGVhcnNvbiIpKSkKcm93LnNlciA8LSBzZXJpYXRlKGRzdCwgbWV0aG9kID0iUjJFIikgIyJSMkUiCmdlbmUub3JkZXIgPC0gcm93bmFtZXMoTnI0YTJfY3VydmVfbWF0cml4W2dldF9vcmRlcihyb3cuc2VyKSxdKQoKYW5uby5jb2xvcnMgPC0gbGlzdChsaW5lYWdlID0gYyhOZml4PSIjY2MzOTFiIiwgTnI0YTI9IiMwMjZjOWEiKSwKICAgICAgICAgICAgICAgICAgICBHZW5lLkNsdXN0ZXJzID0gYyhDbHVzdC4xID0iI2I3OWYwYiIgLCBDbHVzdC4yPSIjZTQ2QjZiIiwgQ2x1c3QuMz0iI2U3ODIzYSIsIENsdXN0LjQ9IiNjYzg3NzgiLCBDbHVzdC41PSIjNjhiMDQxIiwgQ2x1c3QuNj0iIzVhYjc5MyIpKQoKCnBoZWF0bWFwOjpwaGVhdG1hcChjdXJ2ZV9tYXRyaXhbZ2VuZS5vcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKDIwMDoxMDEsICNOZml4IHBvaW50cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMToxMDApXSwgI05yNGEyIHBvaW50cwogICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEYsCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9yb3cgPSBOcjRhMi5HZW5lLmR5bmFtaXF1ZSAlPiUgZHBseXI6OnNlbGVjdChHZW5lLkNsdXN0ZXJzKSwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fY29sID0gZGF0YS5mcmFtZShsaW5lYWdlID0gcmVwKGMoIk5yNGEyIiwgIk5maXgiKSwgZWFjaD0xMDApKSwKICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25fY29sb3JzID0gYW5uby5jb2xvcnMsCiAgICAgICAgICAgICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwKICAgICAgICAgICAgICAgICAgIHNob3dfcm93bmFtZXMgPSBULAogICAgICAgICAgICAgICAgICAgZm9udHNpemVfcm93ID0gMiwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gcmV2KGJyZXdlci5wYWwoMTEsIlJkQnUiKSksCiAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoLTIuNSwyLjUsIGxlbmd0aC5vdXQgPSAxMSksCiAgICAgICAgICAgICAgICAgICBtYWluID0gIk5yNGEyIGNlbGxzIGVucmljaGVkIGdlbmVzIGV4cHJlc3Npb24gYWxvbmcgcHNldWRvdGltZSIpCmBgYAoKCiMjIE5maXggbmV1cm9ucyBzcGVjaWZpYyB0cmFuc2NyaXB0aW9uYWwgdHJhamVjdG9yaWVzCgpgYGB7cn0KIyBFeHRyYWN0IE5maXggbmV1cm9ucyB0cmFqZWN0b3J5IGdlbmVzCk5maXgucmVzIDwtIGFzLmRhdGEuZnJhbWUoU3BldWRvdGltZS5saW5lYWdlcy5kaWZmLmZpbHRlcmVkW1NwZXVkb3RpbWUubGluZWFnZXMuZGlmZi5maWx0ZXJlZCRBQkNzIDwgMCxdKQpOZml4LmdlbmVzIDwtIHJvdy5uYW1lcyhOZml4LnJlcykKTmZpeF9jdXJ2ZV9tYXRyaXggPC0gTmZpeF9jdXJ2ZV9tYXRyaXhbcm93bmFtZXMoTmZpeF9jdXJ2ZV9tYXRyaXgpICVpbiUgTmZpeC5nZW5lcywgXQpgYGAKCmBgYHtyfQojIEdyb3VwZSBnZW5lcyBpbiA2IGNsdXN0ZXJzIGJ5IHBhcnRpdGlvbmluZyByb3VuZCBtZWRvaWRzCk5maXguZ2VuZXMuY2x1c3RlcnMgPC0gY2x1c3Rlcjo6cGFtKGFzLmRpc3QoKDEgLSBjb3IodChOZml4X2N1cnZlX21hdHJpeCksIG1ldGhvZCA9ICJwZWFyc29uIikpKSwgaz02KQoKIyBDcmVhdGUgYSBkYXRhZnJhbWUgc3RvcmluZyBERUcgdGVzdCBhbmQgY2x1c3RlcmluZyByZXN1bHRzCk5maXguR2VuZS5keW5hbWlxdWUgPC0gZGF0YS5mcmFtZShHZW5lPSBuYW1lcyhOZml4LmdlbmVzLmNsdXN0ZXJzJGNsdXN0ZXJpbmcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWw9TmZpeC5yZXMkcHZhbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdmFsPU5maXgucmVzJHF2YWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQUJDcz1OZml4LnJlcyRBQkNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEdlbmUuQ2x1c3RlcnM9IHBhc3RlMCgiQ2x1c3QuIiwgTmZpeC5nZW5lcy5jbHVzdGVycyRjbHVzdGVyaW5nKSkgJT4lIGFycmFuZ2UoR2VuZS5DbHVzdGVycykKCnJvdy5uYW1lcyhOZml4LkdlbmUuZHluYW1pcXVlKSA8LSBOZml4LkdlbmUuZHluYW1pcXVlJEdlbmUKCndyaXRlLnRhYmxlKE5maXguR2VuZS5keW5hbWlxdWUsICIuL05maXguR2VuZS5keW5hbWlxdWUuY3N2Iiwgc2VwPSI7IikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSwgNSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gN0MifQojIE9yZGVyIHRoZSByb3cgdXNpbmcgc2VyaWF0aW9uCmRzdCA8LSBhcy5kaXN0KCgxLWNvcihzY2FsZSh0KE5maXhfY3VydmVfbWF0cml4KSksIG1ldGhvZCA9ICJwZWFyc29uIikpKQpyb3cuc2VyIDwtIHNlcmlhdGUoZHN0LCBtZXRob2QgPSJSMkUiKQpnZW5lLm9yZGVyIDwtIHJvd25hbWVzKE5maXhfY3VydmVfbWF0cml4W2dldF9vcmRlcihyb3cuc2VyKSxdKQoKCnBoZWF0bWFwOjpwaGVhdG1hcChjdXJ2ZV9tYXRyaXhbZ2VuZS5vcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKDIwMDoxMDEsICNOZml4IHBvaW50cwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMToxMDApXSwgI05yNGEyIHBvaW50cwogICAgICAgICAgICAgICAgICAgc2NhbGUgPSAicm93IiwKICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEYsCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9yb3cgPSBOZml4LkdlbmUuZHluYW1pcXVlICU+JSBkcGx5cjo6c2VsZWN0KEdlbmUuQ2x1c3RlcnMpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2wgPSBkYXRhLmZyYW1lKGxpbmVhZ2UgPSByZXAoYygiTnI0YTIiLCAiTmZpeCIpLCBlYWNoPTEwMCkpLAogICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnMgPSBhbm5vLmNvbG9ycywKICAgICAgICAgICAgICAgICAgIHNob3dfY29sbmFtZXMgPSBGLAogICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IFQsCiAgICAgICAgICAgICAgICAgICBmb250c2l6ZV9yb3cgPSAyLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSByZXYoYnJld2VyLnBhbCgxMSwiUmRCdSIpKSwKICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgtMi41LDIuNSwgbGVuZ3RoLm91dCA9IDExKSwKICAgICAgICAgICAgICAgICAgIG1haW4gPSAiTmZpeCBjZWxscyBlbnJpY2hlZCBnZW5lcyBleHByZXNzaW9uIGFsb25nIHBzZXVkb3RpbWUiKQpgYGAKIyBQbG90IHJlbGV2YW50IGdlbmVzIHRyZW5kCgpgYGB7cn0KIyBsb2FkIGN1c3RvbSBwbG90dGluZyBmdW5jdGlvbnMKc291cmNlKCIuL2Z1bmN0aW9ucy9UcmFqZWN0b3JpZXNQbG90RnVuY3Rpb25zLlIiKQpgYGAKCmBgYHtyIGZpZy5kaW09YygxMCw1KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiA3RSJ9ClBsb3QuR2VuZXMudHJlbmQoQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIk5maWIiLCAiRGJ4MSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZXVyb2Q2IiwgIlBieDMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiUGNwNCIsICJCYXJobDIiKSwKICAgICAgICAgICAgICAgICBjb2xvci5ieSA9ICJsaW5lYWdlIiwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDksNSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gN0UifQpQbG90LkdlbmVzLnRyZW5kKEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJOZXVyb2Q0IiwgIk5ldXJvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiWmZoeDMiLCAiVHViYjMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiSGV5MSIsICJNYXB0IiksCiAgICAgICAgICAgICAgICAgY29sb3IuYnkgPSAibGluZWFnZSIsCiAgICAgICAgICAgICAgICAgVXNlLnNjYWxlLmRhdGEgPSBGKQpgYGAKCmBgYHtyIGZpZy5kaW09Yyg5LDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIFM3QiJ9ClBsb3QuR2VuZXMudHJlbmQoQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIlRicjEiLCAiRW14MSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJOZXVyb2QxIiwgIkhleTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiTmV1cm9kMiIsICJGbHJ0MyIpLAogICAgICAgICAgICAgICAgIGNvbG9yLmJ5ID0gImxpbmVhZ2UiLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSw1KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiBTN0IifQpQbG90LkdlbmVzLnRyZW5kKEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJOZmlhIiwgIkRtcnQzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNucjEiLCAiU2xjMzBhMTAiKSwKICAgICAgICAgICAgICAgICBjb2xvci5ieSA9ICJsaW5lYWdlIiwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDEwLDUpLCBmaWcuY2FwPSAiTWFudXNjcmlwdCBGaWcuIFM3QiJ9ClBsb3QuR2VuZXMudHJlbmQoQWxsY2VsbHMuZGF0YSwKICAgICAgICAgICAgICAgICBnZW5lcyA9IGMoIk1laXMyIiwgIkdtMjkyNjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiTnIyZjIiLCAiRGxldTciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiWmJ0YjIwIiwgIlN2aWwiKSwKICAgICAgICAgICAgICAgICBjb2xvci5ieSA9ICJsaW5lYWdlIiwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYAoKYGBge3IgZmlnLmRpbT1jKDksNSksIGZpZy5jYXA9ICJNYW51c2NyaXB0IEZpZy4gUzdCIn0KUGxvdC5HZW5lcy50cmVuZChBbGxjZWxscy5kYXRhLAogICAgICAgICAgICAgICAgIGdlbmVzID0gYygiRXBoYTMiLCAiUGRsaW00IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRveCIsICJUZmFwMmMiKSwKICAgICAgICAgICAgICAgICBjb2xvci5ieSA9ICJsaW5lYWdlIiwKICAgICAgICAgICAgICAgICBVc2Uuc2NhbGUuZGF0YSA9IEYpCmBgYApgYGB7ciBmaWcuZGltPWMoOSw1KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiBTN0IifQpQbG90LkdlbmVzLnRyZW5kKEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJFcGhhMyIsICJQZGxpbTQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiVG94IiwgIlRmYXAyYyIpLAogICAgICAgICAgICAgICAgIGNvbG9yLmJ5ID0gImxpbmVhZ2UiLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgpgYGB7ciBmaWcuZGltPWMoOSw1KSwgZmlnLmNhcD0gIk1hbnVzY3JpcHQgRmlnLiBTN0IifQpQbG90LkdlbmVzLnRyZW5kKEFsbGNlbGxzLmRhdGEsCiAgICAgICAgICAgICAgICAgZ2VuZXMgPSBjKCJOZXVyb2cxIiwgIkVvbWVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJ0ZzIiLCAiRm94ZzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiRW14MiIpLAogICAgICAgICAgICAgICAgIGNvbG9yLmJ5ID0gImxpbmVhZ2UiLAogICAgICAgICAgICAgICAgIFVzZS5zY2FsZS5kYXRhID0gRikKYGBgCgojIFNlc3Npb24gSW5mbwpgYGB7cn0KI2RhdGUKZm9ybWF0KFN5cy50aW1lKCksICIlZCAlQiwgJVksICVILCVNIikKCiNQYWNrYWdlcyB1c2VkCnNlc3Npb25JbmZvKCkKYGBg